using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Input;
using Oops.Xna.Framework;
using Oops.Xna.Framework.Physics;
using Oops.Xna.Framework.GameState;
using Oops.Xna.Framework.Viewpoint;
using Oops.Xna.Framework.Viewpoint.Cameras;
using Oops.Xna.Framework.Physics.CollisionSystems;

namespace Oops.Xna.Framework.Testing.App
{
	public class MainMenuScreen : GameScreen, ICollisionCallback
	{
		// The states of the main menu screen.
		private enum MenuState
		{
			Blank,
			None,
			Main,
			CollisionWithPlane,
			BoxofBalls,
			StackedBoxes,
			CompositeShapes,
			Picking,
			Constraints,
			CollisionWithModelMesh,
			Animation,
			CollisionWithHeightmap,
			Exit
		}

		// Initial blank timing.
		private static TimeSpan BlankTime = TimeSpan.FromSeconds(5.0D);

		// Screen state.
		private MenuState state;

		// Game components.
		private ViewpointComponent viewpoint;
		private PhysicsComponent physics;

		private Random random;

		// Collision shapes.
		private CollisionSphere[] spheres = new CollisionSphere[15];
		private CollisionBox[] boxes = new CollisionBox[15];
		private CollisionPlane plane = new CollisionPlane();

		// Graphic resources.
		private Texture2D sphereTexture;
		private Texture2D boxTexture;

		// Drawing resources.
		private BasicEffect basicEffect;

		// Drawing helpers.
		private VertexDeclaration vertexDeclaration;
		private Sphere sphere = new Sphere(10, 16);
		private Box box = new Box();

		// Audio resources
		private WaveBank waveBank;
		private SoundBank soundBank;
		private Cue musicCue;

		public MainMenuScreen(Game game)
			: base(game, "MainMenu")
		{
			// Create screen-specific components.
			this.viewpoint = new ViewpointComponent(this.Game);
			this.physics = new PhysicsComponent(this.Game, new SimpleCollisionSystem(), this);

			// Add the components to the screen's game component collection.
			this.Components.Add(this.viewpoint);
			this.Components.Add(this.physics);
		}

		#region GameScreen Members

		public override void Enter(GameTime gameTime, ref GameScreen previousScreen)
		{
			// Play the music.
			if (this.musicCue == null || !this.musicCue.IsPlaying)
			{
				this.musicCue = this.soundBank.GetCue("music");
				this.musicCue.Play();
			}

			// There should be no previous screen processing.
			previousScreen = null;

			// Call inherited method.
			base.Enter(gameTime, ref previousScreen);
		}

		public override bool GetTransition(GameTime gameTime, ref GameScreen newScreen)
		{
			if (this.GameStateService.CurrentScreen == this)
			{
				// Get the prompt screen.
				PromptScreen promptScreen = this.GameStateService.Screens["Prompt"] as PromptScreen;

				switch (this.state)
				{
					case MenuState.Main:
						// Show the main menu options.
						promptScreen.Initialize(
							"Oops! Framework for XNA",
							new PromptCallback(this.OnPromptMain),
							"1. Collision with Plane",
							"2. Box of Balls",
							"3. Stacked Boxes",
							"4. Composite Shapes",
							"5. Picking",
							"6. Constaints",
							"7. Collision with Mesh",
							"8. Animation",
							"9. Collision with Heightmap",
							"Exit");

						// Display the prompt screen.
						newScreen = promptScreen;

						break;

					case MenuState.CollisionWithPlane:
						// Show the example options.
						promptScreen.Initialize(
							"1. Collision with Plane||Just a bunch of shapes dropped|from a random distance",
							new PromptCallback(this.OnPromptExample1));

						// Display the prompt screen.
						newScreen = promptScreen;

						break;

					case MenuState.BoxofBalls:
						// Show the example options.
						promptScreen.Initialize(
							"2. Box of Balls||A box...of balls.",
							new PromptCallback(this.OnPromptExample2));

						// Display the prompt screen.
						newScreen = promptScreen;

						break;

					case MenuState.StackedBoxes:
						// Show the example options.
						promptScreen.Initialize(
							"3. Stacked Boxes|| 80% of the time it works|everytime.",
							new PromptCallback(this.OnPromptExample3));

						// Display the prompt screen.
						newScreen = promptScreen;

						break;

					case MenuState.CompositeShapes:
						// Show the example options.
						promptScreen.Initialize(
							"4. Composite Shapes||(Inertia tensor is off a bit)",
							new PromptCallback(this.OnPromptExample4));

						// Display the prompt screen.
						newScreen = promptScreen;

						break;

					case MenuState.Picking:
						// Show the example options.
						promptScreen.Initialize(
							"5. Picking||Control the cursor w/ a game pad,|WASD keyboard controls or|a mouse.",
							new PromptCallback(this.OnPromptExample5));

						// Display the prompt screen.
						newScreen = promptScreen;

						break;

					case MenuState.Constraints:
						// Show the example options.
						promptScreen.Initialize(
							"6.  Constraints||On the road to ragdolls!!",
							new PromptCallback(this.OnPromptExample6));

						// Display the prompt screen.
						newScreen = promptScreen;

						break;

					case MenuState.CollisionWithModelMesh:
						// Show the example options.
						promptScreen.Initialize(
							"7. Collision with a Mesh||A mesh you say?",
							new PromptCallback(this.OnPromptExample7));

						// Display the prompt screen.
						newScreen = promptScreen;

						break;

					case MenuState.Animation:
						// Show the example options.
						promptScreen.Initialize(
							"8. Animation||Ignore if you want.",
							new PromptCallback(this.OnPromptExample8));

						// Display the prompt screen.
						newScreen = promptScreen;

						break;

					case MenuState.CollisionWithHeightmap:
						// Show the example options.
						promptScreen.Initialize(
							"9. Collision with a Heightmap||Isn't a heightmap|a special version of a mesh...|make it so.",
							new PromptCallback(this.OnPromptExample9));

						// Display the prompt screen.
						newScreen = promptScreen;

						break;

					case MenuState.Exit:
						// Show the exit options.
						promptScreen.Initialize(
								"Are you sure that you want to exit?",
								new PromptCallback(this.OnPromptExit),
								"Yes", "No");

						// Display the prompt screen.
						newScreen = promptScreen;

						break;
				}
			}

			return true;
		}

		#endregion

		#region DrawableGameComponent Members

		protected override void LoadContent()
		{
			// Load all the used texture resources.
			this.sphereTexture = this.Game.GetContent().Load<Texture2D>(@".\Content\Textures\sphere");
			this.boxTexture = this.Game.GetContent().Load<Texture2D>(@".\Content\Textures\box");

			// Create and initialize a basic effect for drawing.
			this.basicEffect = new BasicEffect(this.GraphicsDevice, null);
			this.basicEffect.EnableDefaultLighting();
			this.basicEffect.TextureEnabled = true;
			this.basicEffect.PreferPerPixelLighting = true;

			// Create the vertect declaration for primitive drawing.
			this.vertexDeclaration = new VertexDeclaration(this.GraphicsDevice, VertexPositionNormalTexture.VertexElements);

			// Call inherited method.
			base.LoadContent();
		}

		protected override void UnloadContent()
		{
			// Dispose of the basic effect and vertex declaration.
			if (this.basicEffect != null)
			{
				this.basicEffect.Dispose();
			}
			if (this.vertexDeclaration != null)
			{
				this.vertexDeclaration.Dispose();
			}

			// Call inherited method.
			base.UnloadContent();
		}

		#endregion

		#region GameComponent Members

		protected override void Dispose(bool disposing)
		{
			if (disposing)
			{
				lock (this)
				{
					// Dispose of the music audio resources.
					if (this.soundBank != null)
					{
						this.soundBank.Dispose();
					}
					if (this.waveBank != null)
					{
						this.waveBank.Dispose();
					}
				}
			}

			// Call inherited method.
			base.Dispose(disposing);
		}

		#endregion

		#region IGameComponent Members

		public override void Initialize()
		{
			// Initialize the physics component.
			this.physics.Speed = 0.5f;

			// Initialize the viewpoint component.
			StaticCamera camera = new StaticCamera(this.Game, "Static");
			camera.IsViewUpdated = false;
			camera.View = Matrix.CreateLookAt(new Vector3(0.0f, 55.0f, 35.0f), new Vector3(0.0f, 70.0f, 0.0f), Vector3.Up);
			this.viewpoint.Cameras.Add(camera);

			// Initialize the randomizer.
			this.random = new Random();

			// Initialize collision shapes.
			this.InitializeCollisionShapes();

			// Initialize the collision plane.
			this.plane.Normal = Vector3.Up;
			this.plane.Distance = 0.0f;

			CollisionGroup collisionGroup = new CollisionGroup();
			collisionGroup.CollisionShapes.Add(this.plane);

			this.physics.CollisionSystem.CollisionGroups.Add(collisionGroup);

			// Call inherited method.
			base.Initialize();

			// Load the wave and sound bank for music.
			this.waveBank = new WaveBank(this.AudioService.AudioEngine, @".\Content\Audio\Music.xwb");
			this.soundBank = new SoundBank(this.AudioService.AudioEngine, @".\Content\Audio\Music.xsb");
		}

		#endregion

		private void InitializeCollisionShapes()
		{
			// Iterate on all box shapes.
			for (int i = 0; i < this.boxes.Length; i++)
			{
				// Create the box.
				CollisionBox box = new CollisionBox();
				box.Extents = random.NextVector3(1.0f, 5.0f);
				box.StaticFriction = 0.5f;
				box.DynamicFriction = 0.5f;
				box.Restitution = 0.6f;

				// Create a rigid body for the collision box.
				RigidBody rigidBody = new RigidBody();
				rigidBody.Flags = RigidBodyFlags.None;
				rigidBody.LinearDamping = 0.3f;
				rigidBody.AngularDamping = 0.3f;

				// Add the sphere to the rigid body and initialize.
				rigidBody.CollisionGroup.CollisionShapes.Add(box);
				rigidBody.CalculateMassProperties(1.0f);

				Vector3 position = random.NextVector3(-90.0f, 90.0f, 10.0f, 16.0f, -90.0f, 90.0f);
#if QUATERNION_ORIENTATION
				Quaternion orientation = Quaternion.Normalize(random.NextQuaternion(-90.0f, 90.0f, 50.0f, 70.0f, -90.0f, 90.0f));
#else
				Matrix orientation = Matrix.CreateFromQuaternion(Quaternion.Normalize(random.NextQuaternion(-90.0f, 90.0f, 50.0f, 70.0f, -90.0f, 90.0f)));
#endif
				rigidBody.UpdateTransform(ref position, ref orientation);

				rigidBody.Rotation = random.NextVector3(-0.5f, 0.5f);

				// Assign the box to the  shape list.
				this.boxes[i] = box;
				this.physics.RigidBodies.Add(rigidBody);
			}

			// Iterate on all sphere shapes.
			for (int i = 0; i < this.spheres.Length; i++)
			{
				// Create and initialize the sphere.
				CollisionSphere sphere = new CollisionSphere();
				sphere.Radius = (float)(random.NextDouble() * 3.0D) + 1.0f;
				sphere.StaticFriction = 0.8f;
				sphere.DynamicFriction = 0.8f;
				sphere.Restitution = 0.8f;

				// Create a rigid body for the collision sphere.
				RigidBody rigidBody = new RigidBody();
				rigidBody.Flags = RigidBodyFlags.None;
				rigidBody.LinearDamping = 0.3f;
				rigidBody.AngularDamping = 0.3f;

				// Add the sphere to the rigid body and initialize.
				rigidBody.CollisionGroup.CollisionShapes.Add(sphere);
				rigidBody.CalculateMassProperties(1.0f);

				Vector3 position = random.NextVector3(-20.0f, 20.0f, 10.0f, 10.0f, -20.0f, 20.0f);
#if QUATERNION_ORIENTATION
				Quaternion orientation = Quaternion.Normalize(random.NextQuaternion(-90.0f, 90.0f, 50.0f, 70.0f, -90.0f, 90.0f));
#else
				Matrix orientation = Matrix.CreateFromQuaternion(Quaternion.Normalize(random.NextQuaternion(-90.0f, 90.0f, 50.0f, 70.0f, -90.0f, 90.0f)));
#endif
				rigidBody.UpdateTransform(ref position, ref orientation);

				rigidBody.Rotation = random.NextVector3(-0.5f, 0.5f);

				// Assign the sphere to the array.
				this.spheres[i] = sphere;
				this.physics.RigidBodies.Add(rigidBody);
			}
		}

		#region IUpdateable Members

		public override void Update(GameTime gameTime)
		{
			this.physics.EndUpdate();

			// Don't show the main menu options immediately.
			if (this.state == MenuState.Blank)
			{
				if (gameTime.TotalGameTime.TotalSeconds / MainMenuScreen.BlankTime.TotalSeconds >= 1.0D)
				{
					this.state = MenuState.Main;
				}
			}

			// Check if the user(s) want to see the menu.
			bool buttonPressed = false;
			for (int i = 0; i < 4; i++)
			{
				// Check for controller connection status.
				if (this.InputService.IsGamePadConnected(i))
				{
					// Check every action that could be considered a cancellation.
					buttonPressed |= this.InputService.IsGamePadButtonPressed(i, Buttons.A);
					buttonPressed |= this.InputService.IsGamePadButtonPressed(i, Buttons.Start);
				}
			}

			// Check keyboard events too.
			buttonPressed |= this.InputService.IsKeyPressed(Keys.Space);
			buttonPressed |= this.InputService.IsKeyPressed(Keys.Enter);
			buttonPressed |= this.InputService.IsKeyPressed(Keys.Escape);

			// Set the state.
			if (buttonPressed)
			{
				this.state = MenuState.Main;
			}

			this.physics.BeginUpdate(gameTime);

			// Call inherited method.
			base.Update(gameTime);
		}

		#endregion

		#region IDrawable Members

		public override void Draw(GameTime gameTime)
		{
			// Clear the graphics device and assign the vertex declaration.
			this.GraphicsDevice.Clear(ClearOptions.DepthBuffer | ClearOptions.Target, Color.Black, 1.0f, 0);
			this.GraphicsDevice.VertexDeclaration = this.vertexDeclaration;

			// Initialize the basic effect for this iteration.
			this.basicEffect.Begin();
			this.basicEffect.CurrentTechnique.Passes[0].Begin();
			this.basicEffect.View = this.viewpoint.ActiveCamera.View;
			this.basicEffect.Projection = this.viewpoint.ActiveCamera.Projection;

			// Draw all the box shapes.
			this.basicEffect.Texture = this.boxTexture;
			for (int i = 0; i < this.boxes.Length; i++)
			{
#if QUATERNION_ORIENTATION
				this.basicEffect.World = Matrix.CreateScale(this.boxes[i].Extents) * Matrix.CreateFromQuaternion(this.boxes[i].Orientation) * Matrix.CreateTranslation(this.boxes[i].Position);
#else
				this.basicEffect.World = Matrix.CreateScale(this.boxes[i].Extents) * this.boxes[i].Orientation * Matrix.CreateTranslation(this.boxes[i].Position);
#endif
				this.basicEffect.CommitChanges();
				this.GraphicsDevice.DrawUserPrimitives<VertexPositionNormalTexture>(PrimitiveType.TriangleList, this.box.Vertices, 0, this.box.Vertices.Length / 3);
			}

			// Draw all the sphere shapes.
			this.basicEffect.Texture = this.sphereTexture;
			for (int i = 0; i < this.spheres.Length; i++)
			{
#if QUATERNION_ORIENTATION
				this.basicEffect.World = Matrix.CreateScale(this.spheres[i].Radius) * Matrix.CreateFromQuaternion(this.spheres[i].Orientation) * Matrix.CreateTranslation(this.spheres[i].Position);
#else
				this.basicEffect.World = Matrix.CreateScale(this.spheres[i].Radius) * this.spheres[i].Orientation * Matrix.CreateTranslation(this.spheres[i].Position);
#endif
				this.basicEffect.CommitChanges();
				this.GraphicsDevice.DrawUserIndexedPrimitives<VertexPositionNormalTexture>(PrimitiveType.TriangleList, this.sphere.Vertices, 0, this.sphere.Vertices.Length, this.sphere.Indices, 0, this.sphere.Indices.Length / 3);
			}

			// End the basic effect processing.
			this.basicEffect.CurrentTechnique.Passes[0].End();
			this.basicEffect.End();

			// Call inherited method.
			base.Draw(gameTime);
		}

		#endregion

		#region ICollisionCallback Members

		public bool OnCollided(CollisionShape shape0, CollisionShape shape1, ref Vector3 normal, IList<CollisionPoint> points)
		{
			// Determine if a shape collided with the boundary plane.
			CollisionShape shape = null;
			if (shape0 == this.plane)
			{
				shape = shape1;
			}
			else if (shape1 == this.plane)
			{
				shape = shape0;
			}

			// A shape collided with the boundary plane.
			if (shape != null)
			{
				// Any shape that collides with the plane should be given a new position, velocity and rotation.
				Vector3 position = this.random.NextVector3(-15.0f, 15.0f, 10.0f, 10.0f, -15.0f, 15.0f);
				shape.CollisionGroup.RigidBody.UpdateTransform(ref position);

				shape.CollisionGroup.RigidBody.Velocity = this.random.NextVector3(0.0f, 1.0f, 10.0f, 10.0f, 0.0f, 1.0f);
				shape.CollisionGroup.RigidBody.Velocity.Normalize();
				shape.CollisionGroup.RigidBody.Velocity *= 50.0f;

				shape.CollisionGroup.RigidBody.Rotation = this.random.NextVector3(-0.5f, 0.5f);
				shape.CollisionGroup.RigidBody.Rotation.Normalize();
				shape.CollisionGroup.RigidBody.Rotation *= 5.0f;

				// Cancel the collision.  It's just for notification.
				return false;
			}

			// Allow all collisions between shapes.
			return true;
		}

		#endregion

		#region Prompt Handlers

		private bool OnPromptMain(int selectedOption, GameTime gameTime, ref GameScreen newScreen)
		{
			// Check which option was selected.
			switch (selectedOption)
			{
				// Cancel.
				case -1:
					// Set the state.
					this.state = MenuState.None;

					// The prompt screen will not display.
					newScreen = this;
					break;

				// Example 1.
				case 0:
					// Set the state.
					this.state = MenuState.CollisionWithPlane;

					// Display the prompt screen.
					newScreen = this;
					break;

				// Example 2.
				case 1:
					// Set the state.
					this.state = MenuState.BoxofBalls;

					// Display the prompt screen.
					newScreen = this;
					break;

				// Example 3.
				case 2:
					// Set the state.
					this.state = MenuState.StackedBoxes;

					// Display the prompt screen.
					newScreen = this;
					break;

				// Example 4.
				case 3:
					// Set the state.
					this.state = MenuState.CompositeShapes;

					// Display the prompt screen.
					newScreen = this;
					break;

				// Example 5.
				case 4:
					// Set the state.
					this.state = MenuState.Picking;

					// Display the prompt screen.
					newScreen = this;
					break;

				// Example 6.
				case 5:
					// Set the state.
					this.state = MenuState.Constraints;

					// Display the prompt screen.
					newScreen = this;
					break;

				// Example 7.
				case 6:
					// Set the state.
					this.state = MenuState.CollisionWithModelMesh;

					// Display the prompt screen.
					newScreen = this;
					break;

				// Example 8.
				case 7:
					// Set the state.
					this.state = MenuState.Animation;

					// Display the prompt screen.
					newScreen = this;
					break;

				// Example 9.
				case 8:
					// Set the state.
					this.state = MenuState.CollisionWithHeightmap;

					// Display the prompt screen.
					newScreen = this;
					break;

				// Exit.
				case 9:
					// Set the state.
					this.state = MenuState.Exit;

					// Display the prompt screen.
					newScreen = this;
					break;
			}

			return true;
		}

		private bool OnPromptExample1(int selectedOption, GameTime gameTime, ref GameScreen newScreen)
		{
			// Check which option was selected.
			switch (selectedOption)
			{
				// Cancel.
				case -1:
					// Set the state.
					this.state = MenuState.Main;

					// Stay on current screen.
					newScreen = this;
					break;

				// OK.
				case 0:
					// Stop music.
					if (this.musicCue != null && this.musicCue.IsPlaying)
					{
						this.musicCue.Stop(AudioStopOptions.Immediate);
					}

					// Go to the example screen.
					newScreen = this.GameStateService.Screens["Example1"];
					break;
			}

			return true;
		}

		private bool OnPromptExample2(int selectedOption, GameTime gameTime, ref GameScreen newScreen)
		{
			// Check which option was selected.
			switch (selectedOption)
			{
				// Cancel.
				case -1:
					// Set the state.
					this.state = MenuState.Main;

					// Stay on current screen.
					newScreen = this;
					break;

				// OK.
				case 0:
					// Stop music.
					if (this.musicCue != null && this.musicCue.IsPlaying)
					{
						this.musicCue.Stop(AudioStopOptions.Immediate);
					}

					// Go to the example screen.
					newScreen = this.GameStateService.Screens["Example2"];
					break;
			}

			return true;
		}

		private bool OnPromptExample3(int selectedOption, GameTime gameTime, ref GameScreen newScreen)
		{
			// Check which option was selected.
			switch (selectedOption)
			{
				// Cancel.
				case -1:
					// Set the state.
					this.state = MenuState.Main;

					// Stay on current screen.
					newScreen = this;
					break;

				// OK.
				case 0:
					// Stop music.
					if (this.musicCue != null && this.musicCue.IsPlaying)
					{
						this.musicCue.Stop(AudioStopOptions.Immediate);
					}

					// Go to the example screen.
					newScreen = this.GameStateService.Screens["Example3"];
					break;
			}

			return true;
		}

		private bool OnPromptExample4(int selectedOption, GameTime gameTime, ref GameScreen newScreen)
		{
			// Check which option was selected.
			switch (selectedOption)
			{
				// Cancel.
				case -1:
					// Set the state.
					this.state = MenuState.Main;

					// Stay on current screen.
					newScreen = this;
					break;

				// OK.
				case 0:
					// Stop music.
					if (this.musicCue != null && this.musicCue.IsPlaying)
					{
						this.musicCue.Stop(AudioStopOptions.Immediate);
					}

					// Go to the example screen.
					newScreen = this.GameStateService.Screens["Example4"];
					break;
			}

			return true;
		}

		private bool OnPromptExample5(int selectedOption, GameTime gameTime, ref GameScreen newScreen)
		{
			// Check which option was selected.
			switch (selectedOption)
			{
				// Cancel.
				case -1:
					// Set the state.
					this.state = MenuState.Main;

					// Stay on current screen.
					newScreen = this;
					break;

				// OK.
				case 0:
					// Stop music.
					if (this.musicCue != null && this.musicCue.IsPlaying)
					{
						this.musicCue.Stop(AudioStopOptions.Immediate);
					}

					// Go to the example screen.
					newScreen = this.GameStateService.Screens["Example5"];
					break;
			}

			return true;
		}

		private bool OnPromptExample6(int selectedOption, GameTime gameTime, ref GameScreen newScreen)
		{
			// Check which option was selected.
			switch (selectedOption)
			{
				// Cancel.
				case -1:
					// Set the state.
					this.state = MenuState.Main;

					// Stay on current screen.
					newScreen = this;
					break;

				// OK.
				case 0:
					// Stop music.
					if (this.musicCue != null && this.musicCue.IsPlaying)
					{
						this.musicCue.Stop(AudioStopOptions.Immediate);
					}

					// Go to the example screen.
					newScreen = this.GameStateService.Screens["Example6"];
					break;
			}

			return true;
		}

		private bool OnPromptExample7(int selectedOption, GameTime gameTime, ref GameScreen newScreen)
		{
			// Check which option was selected.
			switch (selectedOption)
			{
				// Cancel.
				case -1:
					// Set the state.
					this.state = MenuState.Main;

					// Stay on current screen.
					newScreen = this;
					break;

				// OK.
				case 0:
					// Stop music.
					if (this.musicCue != null && this.musicCue.IsPlaying)
					{
						this.musicCue.Stop(AudioStopOptions.Immediate);
					}

					// Go to the example screen.
					newScreen = this.GameStateService.Screens["Example7"];
					break;
			}

			return true;
		}

		private bool OnPromptExample8(int selectedOption, GameTime gameTime, ref GameScreen newScreen)
		{
			// Check which option was selected.
			switch (selectedOption)
			{
				// Cancel.
				case -1:
					// Set the state.
					this.state = MenuState.Main;

					// Stay on current screen.
					newScreen = this;
					break;

				// OK.
				case 0:
					// Stop music.
					if (this.musicCue != null && this.musicCue.IsPlaying)
					{
						this.musicCue.Stop(AudioStopOptions.Immediate);
					}

					// Go to the example screen.
					newScreen = this.GameStateService.Screens["Example8"];
					break;
			}

			return true;
		}

		private bool OnPromptExample9(int selectedOption, GameTime gameTime, ref GameScreen newScreen)
		{
			// Check which option was selected.
			switch (selectedOption)
			{
				// Cancel.
				case -1:
					// Set the state.
					this.state = MenuState.Main;

					// Stay on current screen.
					newScreen = this;
					break;

				// OK.
				case 0:
					// Stop music.
					if (this.musicCue != null && this.musicCue.IsPlaying)
					{
						this.musicCue.Stop(AudioStopOptions.Immediate);
					}

					// Go to the example screen.
					newScreen = this.GameStateService.Screens["Example9"];
					break;
			}

			return true;
		}

		private bool OnPromptExit(int selectedOption, GameTime gameTime, ref GameScreen newScreen)
		{
			// Check which option was selected.
			switch (selectedOption)
			{
				// Cancel.
				case -1:
					newScreen = this;
					break;

				// Yes.
				case 0:
					// Exit the game.
					this.Game.Exit();
					break;

				// No.
				case 1:
					// Set the state.
					this.state = MenuState.Main;

					// Return to main menu.
					newScreen = this;
					break;
			}

			return true;
		}

		#endregion
	}
}
